<!-- 
  通用图标选择器组件
  使用方法：
  <icon-selector 
    v-model="iconValue" 
    :filter-text="searchText" 
    :show-panel="isShowPanel"
    @close="isShowPanel = false" 
  />

  属性：
  - modelValue: 当前选中的图标名称
  - filterText: 用于过滤图标的文本
  - showPanel: 是否显示图标选择面板
  
  事件：
  - update:modelValue: 当选择图标时触发，返回选中的图标名称
  - close: 当面板关闭时触发
-->
<template>
  <div class="icon-selector">
    <div v-if="showPanel" class="icon-container">
      <div class="icon-list">
        <el-scrollbar>
          <div class="icon-grid">
            <div 
              v-for="icon in filteredIcons" 
              :key="icon"
              class="icon-item"
              :class="{ 'is-selected': modelValue === icon }"
              @click="selectIcon(icon)"
            >
              <el-icon class="icon">
                <component :is="getIconComponent(icon)" />
              </el-icon>
              <div class="icon-name">{{ icon }}</div>
            </div>
          </div>
        </el-scrollbar>
      </div>
      
      <div class="icon-panel-footer">
        <el-button size="small" @click="closeIconPanel">取消</el-button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, onMounted, onUnmounted } from 'vue';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';

/**
 * 组件属性定义
 */
const props = defineProps({
  /**
   * 当前选中的图标名称
   */
  modelValue: {
    type: String,
    default: ''
  },
  
  /**
   * 用于过滤图标的文本
   */
  filterText: {
    type: String,
    default: ''
  },
  
  /**
   * 是否显示图标选择面板
   */
  showPanel: {
    type: Boolean,
    default: false
  }
});

/**
 * 组件事件定义
 */
const emit = defineEmits([
  /**
   * 当选择图标时触发
   * @param {String} iconName - 选中的图标名称
   */
  'update:modelValue', 
  
  /**
   * 当面板关闭时触发
   */
  'close'
]);

// 获取所有Element Plus图标
const iconList = Object.keys(ElementPlusIconsVue).filter(name => name !== 'Menu');

/**
 * 根据过滤文本过滤图标
 */
const filteredIcons = computed(() => {
  if (!props.filterText) {
    return iconList;
  }
  
  return iconList.filter(icon => 
    icon.toLowerCase().includes(props.filterText.toLowerCase())
  );
});

/**
 * 动态获取图标组件
 * @param {String} iconName - 图标名称
 * @returns {Component} - 图标组件
 */
const getIconComponent = (iconName) => {
  if (!iconName) return null;
  return ElementPlusIconsVue[iconName];
};

/**
 * 选择图标
 * @param {String} icon - 选中的图标名称
 */
const selectIcon = (icon) => {
  emit('update:modelValue', icon);
  emit('close');
};

/**
 * 关闭图标面板
 */
const closeIconPanel = () => {
  emit('close');
};

/**
 * 点击外部关闭面板
 * @param {Event} event - 点击事件
 */
const handleClickOutside = (event) => {
  const iconSelector = document.querySelector('.icon-selector');
  if (iconSelector && !iconSelector.contains(event.target)) {
    emit('close');
  }
};

// 添加点击外部关闭面板的事件监听
onMounted(() => {
  document.addEventListener('click', handleClickOutside);
});

// 移除事件监听
onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside);
});
</script>

<style scoped>
.icon-selector {
  width: 100%;
  position: relative;
}

.icon-container {
  position: absolute;
  z-index: 1000;
  width: 100%;
  background-color: white;
  border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  border: 1px solid #dcdfe6;
  margin-top: 5px;
  transition: all 0.3s;
  top: 0;
  left: 0;
}

.icon-list {
  height: 350px;
  overflow-y: auto;
  padding: 12px;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  padding: 8px;
}

.icon-item {
  width: 100%;
  height: 80px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 10px 5px;
  cursor: pointer;
  transition: all 0.2s;
  background-color: #f8f9fb;
  border-radius: 4px;
  box-sizing: border-box;
  border: 1px solid transparent;
}

.icon-item:hover {
  background-color: #f0f2f5;
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.icon-item.is-selected {
  background-color: #ecf5ff;
  color: #409eff;
  border-color: #409eff;
}

.icon {
  font-size: 20px;
  width: 1em;
  height: 1em;
  color: #606266;
  margin-bottom: 8px;
  display: inline-flex;
  justify-content: center;
  align-items: center;
}

.icon-name {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
  text-align: center;
  color: #606266;
  padding: 0 4px;
  box-sizing: border-box;
}

.icon-panel-footer {
  display: flex;
  justify-content: center;
  padding: 8px 16px;
  border-top: 1px solid #e4e7ed;
}

.icon-panel-footer .el-button {
  width: 80px;
}
</style> 